package com.xy.blog.article.domain.dao.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xy.blog.article.api.model.ArticleQuery;
import com.xy.blog.article.domain.dao.IArticleDao;
import com.xy.blog.article.domain.dao.IArticleLikeViewDao;
import com.xy.blog.article.domain.dao.mapper.ArticleContentMapper;
import com.xy.blog.article.domain.dao.mapper.ArticleLikeMapper;
import com.xy.blog.article.domain.dao.mapper.ArticleMapper;
import com.xy.blog.article.domain.dao.mapper.ArticleViewMapper;
import com.xy.blog.article.domain.dao.model.ArticleContentDO;
import com.xy.blog.article.domain.dao.model.ArticleDO;
import com.xy.blog.article.domain.dao.model.ArticleLikeDO;
import com.xy.blog.article.domain.dao.model.ArticleViewDO;
import com.xy.blog.article.domain.exception.ArticleException;
import com.xy.blog.core.id.SnowflakeIdWorker;
import com.xy.blog.core.springmvc.result.page.PageReq;
import com.xy.blog.core.springmvc.result.page.PageResp;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author zanhonglei
 * @version V1.0
 * @Description:
 * @date 2020/5/23
 */
@Repository
public class ArticleDaoImpl implements IArticleDao, IArticleLikeViewDao {


    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private ArticleLikeMapper articleLikeMapper;

    @Autowired
    private ArticleViewMapper articleViewMapper;

    @Autowired
    private ArticleContentMapper articleContentMapper;

    @Override
    public PageResp<ArticleDO> listPage(PageReq<ArticleQuery> req, Set<Long> ids) throws ArticleException {
        ArticleQuery params = req.getParams();
        Page<Object> objects = PageHelper.startPage(req);
        Example example = new Example(ArticleDO.class);
        example.setOrderByClause("orders");
        Example.Criteria criteria = example.createCriteria();
        if (params != null && StringUtils.isNotEmpty(params.getArticleType())) {
            criteria.andEqualTo("articleType", params.getArticleType());
        }
        if (params != null && StringUtils.isNotEmpty(params.getTitle())) {
            criteria.andLike("title", "%" + params.getTitle().trim() + "%");
        }
        if (params != null && StringUtils.isNotEmpty(params.getContent())) {
            criteria.andLike("content", "%" + params.getContent().trim() + "%");
        }
        if (params != null && StringUtils.isNotEmpty(params.getCourse())) {
            criteria.andEqualTo("course", params.getCourse());
        }

        if (params != null && ids != null && !ids.isEmpty()) {
            criteria.andIn("id", ids);
        }
        List<ArticleDO> articleDOS = articleMapper.selectByExample(example);
        return PageResp.data(articleDOS,objects);
    }

    @Override
    public PageResp<ArticleDO> blogHomeList(PageReq<ArticleQuery> req) throws ArticleException {
        ArticleQuery params = req.getParams();
        Page<Object> objects = PageHelper.startPage(req);
        List<ArticleDO> articleDOS = articleMapper.blogHomeList();
        return PageResp.data(articleDOS);
    }

    @Override
    public PageResp<ArticleDO> blogHomeHotList(PageReq<ArticleQuery> req) throws ArticleException {

        return null;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(ArticleDO item) {
        if (item.getId() == null) {
            item.setId(SnowflakeIdWorker.generateId());
        }
        LocalDateTime now = LocalDateTime.now();
        if (item.getCreateTime() == null) {
            item.setCreateTime(now);
        }
        if (item.getUpdateTime() == null) {
            item.setUpdateTime(now);
        }
        articleMapper.insertSelective(item);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ArticleDO articleDO) {
        articleDO.setUpdateTime(LocalDateTime.now());
        articleMapper.updateByPrimaryKeySelective(articleDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        articleMapper.deleteByPrimaryKey(id);
        ArticleContentDO articleContentDO = new ArticleContentDO();
        articleContentDO.setArticleId(id);
        articleContentMapper.delete(articleContentDO);
    }

    @Override
    public List<ArticleDO> select(ArticleDO articleDO) {
        return articleMapper.select(articleDO);
    }

    @Override
    public ArticleDO getById(Long id) {
        return articleMapper.selectByPrimaryKey(id);
    }

    @Override
    public ArticleContentDO getContentById(Long id) {
        ArticleContentDO articleContentDO = new ArticleContentDO();
        articleContentDO.setArticleId(id);
        return articleContentMapper.selectOne(articleContentDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addContent(ArticleContentDO articleContentDO) {
        LocalDateTime now = LocalDateTime.now();
        articleContentDO.setCreateTime(now);
        articleContentDO.setUpdateTime(now);
        articleContentDO.setId(SnowflakeIdWorker.generateId());
        articleContentMapper.insertSelective(articleContentDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateContent(ArticleContentDO articleContentDO) {
        Example example = new Example(ArticleContentDO.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("articleId", articleContentDO.getArticleId());
        articleContentMapper.updateByExampleSelective(articleContentDO, example);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteContentByArticleId(Long id) {
        ArticleContentDO articleContentDO = new ArticleContentDO();
        articleContentDO.setArticleId(id);
        articleContentMapper.delete(articleContentDO);
    }

    @Override
    public Integer getMaxOrderByCategoryId(Long id) {
        return articleMapper.getMaxOrderByCategoryId(id);
    }

    @Override
    public Integer getMaxOrderBySpecialColumn(Long id) {
        return articleMapper.getMaxOrderBySpecialColumnId(id);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addLikeCount(ArticleLikeDO item) {
        // Redis

        ArticleLikeDO query = new ArticleLikeDO();
        query.setArticleId(item.getArticleId());
        List<ArticleLikeDO> select = articleLikeMapper.select(query);
        if (select != null && !select.isEmpty()) {
            ArticleLikeDO articleLikeDO = select.get(0);
            articleLikeDO.setCount(item.getCount() + articleLikeDO.getCount());
            articleLikeMapper.updateByPrimaryKeySelective(articleLikeDO);
        } else {
            Long aLong = SnowflakeIdWorker.generateId();
            item.setId(aLong);
            articleLikeMapper.insert(item);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addViewCount(ArticleViewDO item) {
        // Redis

        ArticleViewDO query = new ArticleViewDO();
        query.setArticleId(item.getArticleId());
        List<ArticleViewDO> select = articleViewMapper.select(query);
        if (select != null && !select.isEmpty()) {
            ArticleViewDO update = select.get(0);
            update.setCount(item.getCount() + update.getCount());
            articleViewMapper.updateByPrimaryKeySelective(update);
        } else {
            Long aLong = SnowflakeIdWorker.generateId();
            item.setId(aLong);
            articleViewMapper.insert(item);
        }
    }

    @Override
    public Map<Long, Long> getLikeCountByArticleId(List<Long> ids) {
        Map<Long, Long> map = new HashMap<>();
        if (ids.isEmpty()) {
            return map;
        }
        List<ArticleLikeDO> articleLikeDOS = articleLikeMapper.selectBatchByArticleIds(ids);
        articleLikeDOS.forEach(item->{
            map.put(item.getArticleId(), item.getCount());
        });
        return map;
    }

    @Override
    public Map<Long, Long> getViewCountByArticleId(List<Long> ids) {
        Map<Long, Long> map = new HashMap<>();
        if (ids.isEmpty()) {
            return map;
        }
        List<ArticleViewDO> articleViewDOS = articleViewMapper.selectBatchByArticleIds(ids);
        articleViewDOS.forEach(item->{
            map.put(item.getArticleId(), item.getCount());
        });
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteLikeByArticleId(Long id) {
        ArticleLikeDO articleLikeDO = new ArticleLikeDO();
        articleLikeDO.setArticleId(id);
        articleLikeMapper.delete(articleLikeDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteViewByArticleId(Long id) {
        ArticleViewDO articleViewDO = new ArticleViewDO();
        articleViewDO.setArticleId(id);
        articleViewMapper.delete(articleViewDO);
    }
}
